home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / executor / ex_utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  38.1 KB  |  1,422 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    ex_utils.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    miscellanious executor utility routines
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    ExecAssignNodeBaseInfo    \
  10.  *    ExecAssignDebugHooks     >  preforms misc work done in all the
  11.  *    ExecAssignExprContext    /   init node routines.
  12.  *
  13.  *    ExecGetTypeInfo          \
  14.  *    ExecMakeTypeInfo       \
  15.  *    ExecOrderTypeInfo        \
  16.  *    ExecSetTypeInfo          |  old execCStructs interface
  17.  *    ExecFreeTypeInfo       |  code from the version 1
  18.  *    ExecMakeSkeys             |  lisp system.  These should
  19.  *    ExecSetSkeys             |  go away or be updated soon.
  20.  *    ExecSetSkeysValue       |  -cim 11/1/89
  21.  *    ExecFreeSkeys             |
  22.  *    ExecMakeTLValues       |
  23.  *    ExecSetTLValues          /
  24.  *    ExecFreeTLValues     /
  25.  *    ExecTupleAttributes    /
  26.  *
  27.  *    get_innerPlan    \  convience accessors to eliminate confusion
  28.  *    get_outerPlan    /    between right/left inner/outer
  29.  *
  30.  *    QueryDescGetTypeInfo - moved here from main.c
  31.  *                am not sure what uses it -cim 10/12/89
  32.  *
  33.  *    ExecCollect           \
  34.  *    ExecUniqueCons            \
  35.  *    ExecGetVarAttlistFromExpr    >    support routines for
  36.  *    ExecGetVarAttlistFromTLE    /    ExecInitScanAttributes
  37.  *    ExecMakeAttsFromList       /
  38.  *
  39.  *    ExecInitScanAttributes    \    creates/destroys array of attribute
  40.  *    ExecFreeScanAttributes    /    numbers actually examined by the executor
  41.  *                    (needed by the rule manager -cim)
  42.  *
  43.  *   NOTES
  44.  *    This file has traditionally been the place to stick misc.
  45.  *    executor support stuff that doesn't really go anyplace else.
  46.  *    
  47.  *   IDENTIFICATION
  48.  *    $Header: /private/postgres/src/executor/RCS/ex_utils.c,v 1.10 1992/08/21 05:38:56 mer Exp $
  49.  * ----------------------------------------------------------------
  50.  */
  51.  
  52. #include "executor/executor.h"
  53. #include "nodes/relation.h"    /* needed before including keys.h */
  54. #include "planner/keys.h"    /* needed for definition of INNER */
  55.  
  56.  RcsId("$Header: /private/postgres/src/executor/RCS/ex_utils.c,v 1.10 1992/08/21 05:38:56 mer Exp $");
  57. /* ----------------------------------------------------------------
  58.  *      global counters for number of tuples processed, retrieved,
  59.  *      appended, replaced, deleted.
  60.  * ----------------------------------------------------------------
  61.  */
  62. int     NTupleProcessed;
  63. int     NTupleRetrieved;
  64. int     NTupleReplaced;
  65. int     NTupleAppended;
  66. int     NTupleDeleted;
  67. int    NIndexTupleInserted;
  68. extern int NIndexTupleProcessed;  /* have to be defined in the access
  69.                          method level so that the cinterface.a
  70.                          will link ok. */
  71.  
  72. /* ----------------------------------------------------------------
  73.  *                statistic functions
  74.  * ----------------------------------------------------------------
  75.  */
  76.  
  77. /* ----------------------------------------------------------------
  78.  *    ResetTupleCount
  79.  * ----------------------------------------------------------------
  80.  */
  81. void
  82. ResetTupleCount()
  83. {
  84.     NTupleProcessed = 0;
  85.     NTupleRetrieved = 0;
  86.     NTupleAppended = 0;
  87.     NTupleDeleted = 0;
  88.     NTupleReplaced = 0;
  89.     NIndexTupleProcessed = 0;
  90. }
  91.  
  92. /* ----------------------------------------------------------------
  93.  *    PrintTupleCount
  94.  * ----------------------------------------------------------------
  95.  */
  96. void
  97. DisplayTupleCount(statfp)
  98. FILE *statfp;
  99. {
  100.     if (NTupleProcessed > 0)
  101.     fprintf(statfp, "!\t%d tuple%s processed, ", NTupleProcessed,
  102.            (NTupleProcessed == 1) ? "" : "s");
  103.     else {
  104.     fprintf(statfp, "!\tno tuples processed.\n");
  105.     return;
  106.       }
  107.     if (NIndexTupleProcessed > 0)
  108.     fprintf(statfp, "%d indextuple%s processed, ", NIndexTupleProcessed,
  109.            (NIndexTupleProcessed == 1) ? "" : "s");
  110.     if (NIndexTupleInserted > 0)
  111.     fprintf(statfp, "%d indextuple%s inserted, ", NIndexTupleInserted,
  112.            (NIndexTupleInserted == 1) ? "" : "s");
  113.     if (NTupleRetrieved > 0)
  114.     fprintf(statfp, "%d tuple%s retrieved. ", NTupleRetrieved,
  115.            (NTupleRetrieved == 1) ? "" : "s");
  116.     if (NTupleAppended > 0)
  117.     fprintf(statfp, "%d tuple%s appended. ", NTupleAppended,
  118.            (NTupleAppended == 1) ? "" : "s");
  119.     if (NTupleDeleted > 0)
  120.     fprintf(statfp, "%d tuple%s deleted. ", NTupleDeleted,
  121.            (NTupleDeleted == 1) ? "" : "s");
  122.     if (NTupleReplaced > 0)
  123.     fprintf(statfp, "%d tuple%s replaced. ", NTupleReplaced,
  124.            (NTupleReplaced == 1) ? "" : "s");
  125.     fprintf(statfp, "\n");
  126. }
  127.  
  128. /* ----------------------------------------------------------------
  129.  *         miscellanious init node support functions
  130.  *
  131.  *    ExecAssignNodeBaseInfo    - assigns the baseid field of the node
  132.  *    ExecAssignDebugHooks    - assigns the node's debugging hooks
  133.  *    ExecAssignExprContext    - assigns the node's expression context
  134.  * ----------------------------------------------------------------
  135.  */
  136.  
  137. /* ----------------
  138.  *    ExecGetPrivateState
  139.  *
  140.  *    This is used to get a pointer to a node's private state.
  141.  * ----------------
  142.  */
  143. BaseNode
  144. ExecGetPrivateState(node)
  145.     Plan node;
  146. {
  147.     switch(NodeType(node)) {
  148.     case classTag(Result):
  149.     return (BaseNode) get_resstate((Result) node);
  150.     
  151.     case classTag(Append):
  152.     return (BaseNode) get_unionstate((Append) node);
  153.     
  154.     case classTag(NestLoop):
  155.     return (BaseNode) get_nlstate((NestLoop) node);
  156.     
  157.     case classTag(MergeJoin):
  158.     return (BaseNode) get_mergestate((MergeJoin) node);
  159.     
  160.     case classTag(HashJoin):
  161.     return (BaseNode) get_hashjoinstate((HashJoin) node);
  162.     
  163.     case classTag(SeqScan):
  164.     return (BaseNode) get_scanstate((Scan) node);
  165.     
  166.     case classTag(IndexScan):
  167.     return (BaseNode) get_indxstate((IndexScan) node);
  168.     
  169.     case classTag(Material):
  170.     return (BaseNode) get_matstate((Material) node);
  171.     
  172.     case classTag(Sort):
  173.     return (BaseNode) get_sortstate((Sort) node);
  174.     
  175.     case classTag(Unique):
  176.     return (BaseNode) get_uniquestate((Unique) node);
  177.     
  178.     case classTag(Hash):
  179.     return (BaseNode) get_hashstate((Hash) node);
  180.  
  181.     default:
  182.     return NULL;
  183.     }
  184. }
  185.  
  186. /* ----------------
  187.  *    ExecAssignNodeBaseInfo
  188.  *
  189.  *    as it says, this assigns the baseid field of the node and
  190.  *    increments the counter in the estate.  In addition, it initializes
  191.  *    the base_parent field of the basenode.
  192.  * ----------------
  193.  */
  194. void
  195. ExecAssignNodeBaseInfo(estate, basenode, parent)
  196.     EState    estate;
  197.     BaseNode    basenode;
  198.     Plan    parent;
  199. {
  200.     int        baseid;
  201.     BaseNode    parentstate;
  202.     
  203.     baseid = get_es_BaseId(estate);
  204.     set_base_id(basenode, baseid);
  205.     baseid++;
  206.     set_es_BaseId(estate, baseid);
  207.     
  208.     set_base_parent(basenode, (Pointer) parent);
  209.  
  210.     if (parent != NULL) 
  211.     parentstate = ExecGetPrivateState(parent);
  212.     else
  213.     parentstate = (BaseNode) NULL;
  214.     
  215.     set_base_parent_state(basenode, (Pointer) parentstate);
  216. }
  217.  
  218. /* ----------------
  219.  *    ExecAssignDebugHooks
  220.  *
  221.  *    this assigns the executor's debugging hooks, if we compile
  222.  *    with EXEC_ASSIGNDEBUGHOOKS set.
  223.  * ----------------
  224.  */
  225. void
  226. ExecAssignDebugHooks(node, basenode)
  227.     Plan    node;
  228.     BaseNode    basenode;
  229. {
  230. #ifdef EXEC_ASSIGNDEBUGHOOKS
  231.     HookNode     hook;
  232.     HookFunction proc;
  233.     
  234.     if (_debug_hook_id_ > 0) {
  235.     hook = (HookNode) _debug_hooks_[ _debug_hook_id_ ];
  236.     set_base_hook(basenode, hook); 
  237.     proc = (HookFunction) get_hook_at_initnode(hook);
  238.     if (proc != NULL)
  239.         (*proc)(node, basenode);
  240.     }
  241. #endif EXEC_ASSIGNDEBUGHOOKS
  242. }
  243.  
  244. /* ----------------
  245.  *    ExecAssignExprContext
  246.  *
  247.  *    This initializes the ExprContext field.  It is only necessary
  248.  *    to do this for nodes which use ExecQual or ExecTargetList
  249.  *    because those routines depend on econtext.  Other nodes which
  250.  *    dont have to evaluate expressions don't need to do this.
  251.  * ----------------
  252.  */
  253. void
  254. ExecAssignExprContext(estate, commonstate)
  255.     EState    estate;
  256.     CommonState    commonstate;
  257. {
  258.     ExprContext    econtext;
  259.     ParamListInfo  paraminfo;
  260.     List           rangeTable;
  261.     
  262.     paraminfo = get_es_param_list_info(estate);
  263.     rangeTable = get_es_range_table(estate);
  264.  
  265.     econtext = MakeExprContext(NULL,        /* scan tuple slot */
  266.                    NULL,        /* inner tuple slot */
  267.                    NULL,        /* outer tuple slot */
  268.                    NULL,        /* relation */
  269.                    0,        /* relid */
  270.                    paraminfo,    /* param list info */
  271.                    rangeTable);    /* range table */
  272.  
  273.     set_cs_ExprContext(commonstate, econtext);
  274. }
  275.  
  276. /* ----------------------------------------------------------------
  277.  *    Result slot tuple type and ProjectionInfo support
  278.  * ----------------------------------------------------------------
  279.  */
  280.  
  281. /* ----------------
  282.  *    ExecAssignResultType
  283.  * ----------------
  284.  */
  285. void
  286. ExecAssignResultType(commonstate, execTupDesc, tupDesc)
  287.     CommonState        commonstate;
  288.     ExecTupDescriptor    execTupDesc;
  289.     TupleDescriptor    tupDesc;
  290. {
  291.     TupleTableSlot    slot;
  292.     
  293.     slot = get_cs_ResultTupleSlot(commonstate);
  294.     ExecSetSlotExecDescriptor(slot, execTupDesc);
  295.     (void) ExecSetSlotDescriptor((Pointer) slot, tupDesc);
  296. }
  297.  
  298. /* ----------------
  299.  *    ExecAssignResultTypeFromOuterPlan
  300.  * ----------------
  301.  */
  302. void
  303. ExecAssignResultTypeFromOuterPlan(node, commonstate)
  304.     Plan     node;
  305.     CommonState    commonstate;
  306. {
  307.     Plan        outerPlan;
  308.     ExecTupDescriptor    execTupDesc;
  309.     TupleDescriptor    tupDesc;
  310.     
  311.     outerPlan =   get_outerPlan(node);
  312.     execTupDesc = ExecGetExecTupDesc(outerPlan);
  313.     tupDesc = ExecGetTupType(outerPlan);
  314.     
  315.     ExecAssignResultType(commonstate, execTupDesc, tupDesc);
  316. }
  317.  
  318. /* ----------------
  319.  *    ExecAssignResultTypeFromTL
  320.  * ----------------
  321.  */
  322. void
  323. ExecAssignResultTypeFromTL(node, commonstate)
  324.     Plan     node;
  325.     CommonState    commonstate;
  326. {
  327.     List            targetList;
  328.     Var            tlvar;
  329.     int            i;
  330.     int            len;
  331.     List        tl, tle;
  332.     List        fjtl;
  333.     ExecTupDescriptor    execTupDesc;
  334.     TupleDescriptor    tupDesc;
  335.     int            fjcount;
  336.     int            varlen;
  337.     TupleDescriptor    varTupDesc;
  338.     TupleDescriptor    origTupDesc;
  339.     
  340.     targetList =  get_qptargetlist(node);
  341.     origTupDesc = ExecTypeFromTL(targetList);
  342.     if ((len = ExecTargetListLength(targetList)) != 0)
  343.     execTupDesc = ExecMakeExecTupDesc(len);
  344.     else
  345.     execTupDesc = (ExecTupDescriptor)NULL;
  346.  
  347.     fjtl = LispNil;
  348.     tl = targetList;
  349.     i = 0;
  350.     while (!lispNullp(tl) || !lispNullp(fjtl)) {
  351.     if (!lispNullp(fjtl)) {
  352.         tle = CAR(fjtl);
  353.         fjtl = CDR(fjtl);
  354.       }
  355.     else {
  356.         tle = CAR(tl);
  357.         tl = CDR(tl);
  358.       }
  359.     if (!tl_is_resdom(tle)) {
  360.         /* it is a FJoin */
  361.         fjtl = CDR(tle);
  362.         tle = get_fj_innerNode((Fjoin)CAR(tle));
  363.       }
  364.     if (get_rescomplex((Resdom)CAR(tle))) {
  365.         /* if it is a composite type, i.e., a tuple */
  366.         tlvar = (Var)get_expr(tle);
  367.         Assert(IsA(tlvar,Var));
  368.         varlen = ExecGetVarLen(node, commonstate, tlvar);
  369.         varTupDesc = ExecGetVarTupDesc(node, commonstate, tlvar);
  370.         execTupDesc->data[i] = MakeExecAttDesc(ATTTUP, varlen, varTupDesc);
  371.       }
  372.     else {
  373.         /* this means that it is a base type */
  374.         execTupDesc->data[i] = ExecMakeExecAttDesc(ATTVAL, 1);
  375.         execTupDesc->data[i]->attdesc->data[0] = origTupDesc->data[i];
  376.       }
  377.     i++;
  378.       }
  379.     if (len > 0) {
  380.     tupDesc = ExecTupDescToTupDesc(execTupDesc, len);
  381.     ExecAssignResultType(commonstate, execTupDesc, tupDesc);
  382.     }
  383.     else
  384.     ExecAssignResultType(commonstate,
  385.                  (ExecTupDescriptor)NULL,
  386.                  (TupleDescriptor)NULL);
  387. }
  388.  
  389. /* ----------------
  390.  *    ExecGetResultType
  391.  * ----------------
  392.  */
  393. TupleDescriptor
  394. ExecGetResultType(commonstate)
  395.     CommonState    commonstate;
  396. {
  397.     TupleTableSlot    slot = get_cs_ResultTupleSlot(commonstate);
  398.     
  399.     return 
  400.     ExecSlotDescriptor((Pointer) slot);
  401. }
  402.  
  403. /* ----------------
  404.  *    ExecFreeResultType
  405.  * ----------------
  406.  */
  407. void
  408. ExecFreeResultType(commonstate)
  409.     CommonState    commonstate;
  410. {
  411.     TupleTableSlot    slot;
  412.     TupleDescriptor    tupType;
  413.     
  414.     slot =       get_cs_ResultTupleSlot(commonstate);
  415.     tupType =       ExecSlotDescriptor((Pointer) slot);
  416.     
  417.     ExecFreeTypeInfo((struct attribute **) tupType);    /* BUG -- glass */
  418. }
  419.  
  420.  
  421. /* ----------------
  422.  *    ExecAssignProjectionInfo
  423.  * ----------------
  424.  */
  425. void
  426. ExecAssignProjectionInfo(node, commonstate)
  427.     Plan     node;
  428.     CommonState    commonstate;
  429. {
  430.     ProjectionInfo    projInfo;
  431.     List            targetList;
  432.     int              len;
  433.     Pointer         tupValue;
  434.     
  435.     targetList =  get_qptargetlist(node);
  436.     len =       ExecTargetListLength(targetList);
  437.     tupValue =    (Pointer) ExecMakeTLValues(len);
  438.  
  439.     projInfo =     MakeProjectionInfo(targetList, len, tupValue,
  440.                    get_cs_ExprContext(commonstate),
  441.                    get_cs_ResultTupleSlot(commonstate));
  442.     set_cs_ProjInfo(commonstate, projInfo);
  443. /*
  444.     set_pi_targetlist(projInfo, targetList);
  445.     set_pi_len(projInfo, len);
  446.     set_pi_tupValue(projInfo, tupValue);
  447.     set_pi_exprContext(projInfo, get_cs_ExprContext(commonstate));
  448.     set_pi_slot(projInfo, get_cs_ResultTupleSlot(commonstate));
  449. */
  450. }
  451.  
  452.  
  453. /* ----------------
  454.  *    ExecFreeProjectionInfo
  455.  * ----------------
  456.  */
  457. void
  458. ExecFreeProjectionInfo(commonstate)
  459.     CommonState    commonstate;
  460. {
  461.     ProjectionInfo    projInfo;
  462.     Pointer         tupValue;
  463.  
  464.     /* ----------------
  465.      *    get projection info.  if NULL then this node has
  466.      *  none so we just return.
  467.      * ----------------
  468.      */
  469.     projInfo = get_cs_ProjInfo(commonstate);
  470.     if (projInfo == NULL)
  471.     return;
  472.  
  473.     /* ----------------
  474.      *    clean up memory used.
  475.      * ----------------
  476.      */
  477.     tupValue = get_pi_tupValue(projInfo);
  478.     ExecFreeTLValues(tupValue);
  479.     
  480.     pfree(projInfo);
  481.     set_cs_ProjInfo(commonstate, NULL);
  482. }
  483.  
  484. /* ----------------------------------------------------------------
  485.  *    the following scan type support functions are for
  486.  *    those nodes which are stubborn and return tuples in
  487.  *    their Scan tuple slot instead of their Result tuple
  488.  *    slot..  luck fur us, these nodes do not do projections
  489.  *    so we don't have to worry about getting the ProjectionInfo
  490.  *    right for them...  -cim 6/3/91
  491.  * ----------------------------------------------------------------
  492.  */
  493.  
  494. /* ----------------
  495.  *    ExecGetScanType
  496.  * ----------------
  497.  */
  498. TupleDescriptor
  499. ExecGetScanType(csstate)
  500.     CommonScanState    csstate;
  501. {
  502.     TupleTableSlot slot = (TupleTableSlot)
  503.     get_css_ScanTupleSlot(csstate);
  504.     return ExecSlotDescriptor((Pointer) slot);
  505. }
  506.  
  507. /* ----------------
  508.  *    ExecFreeScanType
  509.  * ----------------
  510.  */
  511. void
  512. ExecFreeScanType(csstate)
  513.     CommonScanState csstate;
  514. {
  515.     TupleTableSlot    slot;
  516.     TupleDescriptor    tupType;
  517.     
  518.     slot =       (TupleTableSlot) get_css_ScanTupleSlot(csstate);
  519.     tupType =       ExecSlotDescriptor((Pointer) slot);
  520.     
  521.     ExecFreeTypeInfo((struct attribute **) tupType); /* bug -- glass */
  522. }
  523.  
  524. /* ----------------
  525.  *    ExecAssignScanType
  526.  * ----------------
  527.  */
  528. void
  529. ExecAssignScanType(csstate, execTupDesc, tupDesc)
  530.     CommonScanState    csstate;
  531.     ExecTupDescriptor    execTupDesc;
  532.     TupleDescriptor    tupDesc;
  533. {
  534.     TupleTableSlot    slot;
  535.     
  536.     slot = (TupleTableSlot) get_css_ScanTupleSlot(csstate);
  537.     (void) ExecSetSlotDescriptor((Pointer) slot, tupDesc);
  538.     ExecSetSlotExecDescriptor(slot, execTupDesc);
  539. }
  540.  
  541. /* ----------------
  542.  *    ExecAssignScanTypeFromOuterPlan
  543.  * ----------------
  544.  */
  545. void
  546. ExecAssignScanTypeFromOuterPlan(node, commonstate)
  547.     Plan     node;
  548.     CommonState    commonstate;
  549. {
  550.     Plan        outerPlan;
  551.     TupleDescriptor    tupDesc;
  552.     ExecTupDescriptor    execTupDesc;
  553.     
  554.     outerPlan =   get_outerPlan(node);
  555.     tupDesc =       ExecGetTupType(outerPlan);
  556.     execTupDesc = ExecGetExecTupDesc(outerPlan);
  557.     
  558.     ExecAssignScanType((CommonScanState) commonstate, execTupDesc, tupDesc);
  559. }
  560.  
  561.  
  562. /* ----------------------------------------------------------------
  563.  *            stuff from execCStructs
  564.  *
  565.  *    execCStructs was a file used in the Lisp system to do
  566.  *    stuff with C-allocated structures.  These routines were
  567.  *    called from the lisp executor across the foreign function
  568.  *    interface.  Since it was easier to just keep these when
  569.  *    we converted from lisp to C, that's what we did.  The usefulness
  570.  *    of these functions should be reevaluated sometime soon and
  571.  *    the code rewritten accordingly once an interface is settled on.
  572.  *    -cim 11/1/89
  573.  * ----------------------------------------------------------------
  574.  */
  575.  
  576. /* ----------------------------------------------------------------
  577.  *    ExecTypeFromTL support routines.
  578.  *
  579.  *    these routines are used mainly from ExecTypeFromTL.
  580.  *    -cim 6/12/90
  581.  *
  582.  * old comments
  583.  *    Routines dealing with the structure 'attribute' which conatains
  584.  *    the type information about attributes in a tuple:
  585.  *
  586.  *    ExecGetTypeInfo(relDesc) --
  587.  *        returns the structure 'attribute' from the relation desc.
  588.  *    ExecMakeTypeInfo(noType) --
  589.  *        returns pointer to array of 'noType' structure 'attribute'.
  590.  *    ExecSetTypeInfo(index, typeInfo, attNum, attLen) --
  591.  *        sets the element indexed by 'index' in typeInfo with
  592.  *        the values: attNum, attLen.
  593.  *    ExecFreeTypeInfo(typeInfo) --
  594.  *        frees the structure 'typeInfo'.
  595.  * ----------------------------------------------------------------
  596.  */
  597.  
  598. /* ----------------
  599.  *    ExecGetTypeInfo
  600.  * ----------------
  601.  */
  602. /**** xxref:
  603.  *           <apparently-unused>
  604.  ****/
  605. Attribute
  606. ExecGetTypeInfo(relDesc)
  607.     Relation     relDesc;
  608. {
  609.     return
  610.     ((Attribute) &relDesc->rd_att);
  611. }
  612.  
  613. /* ----------------
  614.  *    ExecMakeTypeInfo
  615.  *
  616.  *    This creates a pre-initialized array of pointers to
  617.  *    attribute structures.  The structures themselves are
  618.  *    expected to be initialized via calls to ExecSetTypeInfo.
  619.  *
  620.  *    The structure returned is a single area of memory which
  621.  *    looks like:
  622.  *
  623.  *      +------+------+-----+------------+------------+-----+
  624.  *    | ptr0 | ptr1 | ... | attribute0 | attribute1 | ... |
  625.  *      +------+------+-----+------------+------------+-----+
  626.  *    
  627.  *    where ptr0 = &attribute0, ptr1 = &attribute1, etc..
  628.  * ----------------
  629.  */
  630. TupleDescriptor
  631. ExecMakeTypeInfo(nelts)
  632.     int    nelts;
  633. {
  634.     struct attribute     *ap;
  635.     struct attribute    **info;
  636.     int             i;
  637.     int             size;
  638.  
  639.     /* ----------------
  640.      *    calculate the size of the entire structure
  641.      * ----------------
  642.      */
  643.     if (nelts <= 0)
  644.     return NULL;
  645.  
  646.     size = (nelts * sizeof(struct attribute)) +
  647.     ((nelts + 1) * sizeof(struct attribute *));
  648.  
  649.     /* ----------------
  650.      *    allocate the whole structure and initialize all
  651.      *  the pointers in the initial array. The array is made
  652.      *  one element too large so that it is NULL terminated,
  653.      *  just in case..
  654.      * ----------------
  655.      */
  656.     info = (struct attribute **) palloc(size);
  657.     ap =   (struct attribute *) (info + (nelts + 1));
  658.     
  659.     for (i=0; i<nelts; i++) {
  660.     info[i] = ap++;
  661.     }
  662.     info[i] = NULL;
  663.  
  664.     return
  665.     (TupleDescriptor) info;
  666. }
  667.  
  668. /* ----------------
  669.  *    ExecSetTypeInfo
  670.  *
  671.  *    This initializes fields of a single attribute in a
  672.  *    tuple descriptor from the specified parameters.
  673.  *
  674.  *    XXX this duplicates much of the functionality of TupleDescInitEntry.
  675.  *        the routines should be moved to the same place and be rewritten
  676.  *        to share common code.
  677.  * ----------------
  678.  */
  679. void
  680. ExecSetTypeInfo(index, typeInfo, typeID, attNum, attLen, attName, attbyVal)
  681.     int         index;
  682.     struct attribute     **typeInfo;
  683.     ObjectId            typeID;
  684.     int            attNum;
  685.     int            attLen;
  686.     char        *attName;
  687.     Boolean        attbyVal;
  688. {
  689.     struct attribute    *att;
  690.  
  691.     /* ----------------
  692.      *    get attribute pointer and preform a sanity check..
  693.      * ----------------
  694.      */
  695.     att = typeInfo[index];
  696.     if (att == NULL)
  697.     elog(WARN, "ExecSetTypeInfo: trying to assign through NULL");
  698.     
  699.     /* ----------------
  700.      *    assign values to the tuple descriptor, being careful not
  701.      *  to copy a null attName..
  702.      *
  703.      *  XXX it is unknown exactly what information is needed to
  704.      *      initialize the attribute struct correctly so for now
  705.      *        we use 0.  this should be fixed -- otherwise we run the
  706.      *        risk of using garbage data. -cim 5/5/91
  707.      * ----------------
  708.      */
  709.     att->attrelid  = 0;                /* dummy value */
  710.     
  711.     if (attName != (char *) NULL)
  712.     strncpy(att->attname, attName, 16);
  713.     else
  714.     bzero(att->attname, 16);
  715.     
  716.     att->atttypid =     typeID;
  717.     att->attdefrel =     0;            /* dummy value */
  718.     att->attnvals  =     0;            /* dummy value */
  719.     att->atttyparg =     0;            /* dummy value */
  720.     att->attlen =       attLen;
  721.     att->attnum =       attNum;
  722.     att->attbound =     0;            /* dummy value */
  723.     att->attbyval =     attbyVal;
  724.     att->attcanindex =     0;            /* dummy value */
  725.     att->attproc =     0;            /* dummy value */
  726.     att->attnelems =     0;            /* dummy value */
  727.     att->attcacheoff =     -1;
  728. }
  729.  
  730. ExecTupDescriptor
  731. ExecMakeExecTupDesc(len)
  732. int len;
  733. {
  734.     ExecTupDescriptor retval;
  735.  
  736.     retval = (ExecTupDescriptor)palloc(len * sizeof(ExecTupDescriptorData));
  737.     return retval;
  738. }
  739.  
  740. ExecAttDesc
  741. ExecMakeExecAttDesc(tag, len)
  742. AttributeTag tag;
  743. int len;
  744. {
  745.     ExecAttDesc attdesc;
  746.     attdesc = (ExecAttDesc)palloc(sizeof(ExecAttDescData));
  747.     attdesc->tag = tag;
  748.     attdesc->len = len;
  749.     attdesc->attdesc = CreateTemplateTupleDesc(len);
  750.     return attdesc;
  751. }
  752.  
  753. ExecAttDesc
  754. MakeExecAttDesc(tag, len, tupdesc)
  755. AttributeTag tag;
  756. int len;
  757. TupleDescriptor tupdesc;
  758. {
  759.     ExecAttDesc attdesc;
  760.     attdesc = (ExecAttDesc)palloc(sizeof(ExecAttDescData));
  761.     attdesc->tag = tag;
  762.     attdesc->len = len;
  763.     attdesc->attdesc = tupdesc;
  764.     return attdesc;
  765. }
  766.  
  767. /* ----------------
  768.  *    ExecFreeTypeInfo frees the array of attrbutes
  769.  *    created by ExecMakeTypeInfo and returned by ExecTypeFromTL...
  770.  * ----------------
  771.  */
  772. void
  773. ExecFreeTypeInfo(typeInfo)
  774.     struct attribute **typeInfo;
  775. {
  776.     /* ----------------
  777.      *    do nothing if asked to free a null pointer
  778.      * ----------------
  779.      */
  780.     if (typeInfo == NULL)
  781.     return;
  782.  
  783.     /* ----------------
  784.      *    the entire array of typeinfo pointers created by
  785.      *  ExecMakeTypeInfo was allocated with a single palloc()
  786.      *  so we can deallocate the whole array with a single pfree().
  787.      *  (we should not try and free all the elements in the array)
  788.      *  -cim 6/12/90
  789.      * ----------------
  790.      */
  791.     pfree(typeInfo);
  792. }
  793.  
  794. /* ----------------------------------------------------------------
  795.  *    QueryDescGetTypeInfo
  796.  *
  797.  *|    I don't know how this is used, all I know is that it
  798.  *|    appeared one day in main.c so I moved it here. -cim 11/1/89
  799.  * ----------------------------------------------------------------
  800.  */
  801. /**** xxref:
  802.  *           <apparently-unused>
  803.  ****/
  804. List
  805. QueryDescGetTypeInfo(queryDesc)
  806.     List queryDesc;
  807. {
  808.     Plan            plan;
  809.     TupleDesc       tupleType;
  810.     List            targetList;
  811.     
  812.     plan =             QdGetPlan(queryDesc);
  813.     tupleType = (TupleDesc) ExecGetTupType(plan);
  814.     targetList =         get_qptargetlist(plan);
  815.     
  816.     return (List)
  817.     MakeList(lispInteger(ExecTargetListLength(targetList)), tupleType, -1);
  818. }
  819.  
  820. /* ----------------------------------------------------------------
  821.  *           ExecInitScanAttributes support
  822.  * ----------------------------------------------------------------
  823.  */
  824.  
  825. /* --------------------------------
  826.  *    ExecCollect
  827.  *
  828.  *    This function calls its collect function on the results
  829.  *    of calling its apply function on successive elements
  830.  *    of the list passed to it.
  831.  * --------------------------------
  832.  */
  833. /**** xxref:
  834.  *           ExecGetVarAttlistFromExpr
  835.  *           ExecInitScanAttributes
  836.  ****/
  837. List
  838. ExecCollect(l, applyFunction, collectFunction, applyParameters)
  839.     List l;
  840.     List (*applyFunction)();
  841.     List (*collectFunction)();
  842.     List applyParameters;
  843. {
  844.     List cdrEntry;
  845.     List entry;
  846.     List applyResult;
  847.     List collection;
  848.     collection = LispNil;
  849.     
  850.     foreach(cdrEntry, l) {
  851.     entry = CAR(cdrEntry);
  852.     applyResult = (*applyFunction)(entry, applyParameters);
  853.     collection = (*collectFunction)(applyResult, collection);
  854.     }
  855.     
  856.     return collection;
  857. }
  858.  
  859. /* --------------------------------
  860.  *    ExecUniqueCons
  861.  *
  862.  *    This function returns a list of unique integers, given
  863.  *    two lists as input.  Since our lists are short and this
  864.  *    is only done once each query, we don't bother worring
  865.  *    about efficiency.. (this should probably be done in the
  866.  *    planner anyways..)
  867.  *
  868.  *      Note: list2 had better be free of duplicates already.
  869.  *            list1 can have duplicates - they get tossed.
  870.  *
  871.  *    Final list consists elts of list1 on the head of list2,
  872.  *    unless one of the lists is nil, in which case the other
  873.  *    is returned..
  874.  * --------------------------------
  875.  */
  876. /**** xxref:
  877.  *           <apparently-unused>
  878.  ****/
  879. List
  880. ExecUniqueCons(list1, list2)
  881.     List list1;
  882.     List list2;
  883. {
  884.     List     current1;
  885.     List     current2;
  886.     LispValue     current1Int;
  887.     LispValue     current2Int;
  888.     bool    foundDuplicate;
  889.     
  890.     /* ----------------
  891.      *    make sure both lists contain something
  892.      * ----------------
  893.      */
  894.     if (lispNullp(list1))
  895.     return list2;
  896.     
  897.     if (lispNullp(list2))
  898.     return list1;
  899.     
  900.     /* ----------------
  901.      *    for each entry in the first list 
  902.      *     see if it's already in the second list
  903.      *     if so, then move onto the next entry in the first list
  904.      *     if not, then add the entry to the front of the second list.
  905.      *
  906.      *  note: this trashes list1.. non-duplicates are moved to list2
  907.      *        and duplicates are left stranded in memory..
  908.      * ----------------
  909.      */
  910.     
  911.     current1 = list1;
  912.     while (! lispNullp(current1)) {
  913.     current1Int = CAR(current1);
  914.     current2 = list2;
  915.     foundDuplicate = false;
  916.     
  917.     /* ----------------
  918.      *  see if current item from list 1 is already in list2
  919.      * ----------------
  920.      */
  921.     while (! lispNullp(current2)) {
  922.         current2Int = CAR(current2);
  923.         if (CInteger(current2Int) == CInteger(current1Int)) {
  924.         foundDuplicate = true;
  925.         break;
  926.         } 
  927.         current2 = CDR(current2);
  928.     }
  929.     
  930.     /* ----------------
  931.      *  foundDuplicate is now true if current item is in list2
  932.      *  and is false if we traversed all of list2 and no item there
  933.      *  matched it..
  934.      * ----------------
  935.      */
  936.     if (! foundDuplicate) {
  937.         List temp;
  938.         /* ----------------
  939.          *  since current1 is not in list2, move current1 onto the head
  940.          *  of list2 and then move to the next element in list1.
  941.          * ----------------
  942.          */
  943.         temp =          CDR(current1);
  944.         CDR(current1) = list2;
  945.         list2 =         current1;
  946.         current1 =      temp;
  947.     } else {
  948.         /* ----------------
  949.          *  current1 is already in list2 so we just
  950.          *    advance current1 to the next element in list1
  951.          * ----------------
  952.          */
  953.         current1 = CDR(current1);
  954.     }
  955.     }
  956.     
  957.     /* ----------------
  958.      *    at this point, all elts of list1 not originally in list2
  959.      *  are on the head of list2 so we can just return list2.
  960.      * ----------------
  961.      */
  962.     return list2;
  963. }
  964.  
  965. /* --------------------------------
  966.  *    ExecGetVarAttlistFromExpr
  967.  *
  968.  *    This is a recursive function which returns a list
  969.  *    containing the attribute numbers of all var nodes
  970.  * --------------------------------
  971.  */
  972. /**** xxref:
  973.  *           ExecGetVarAttlistFromExpr
  974.  *           ExecGetVarAttlistFromTLE
  975.  ****/
  976. List
  977. ExecGetVarAttlistFromExpr(expr, relationNum)
  978.     Node expr;
  979.     List relationNum;
  980. {
  981.     /* ----------------
  982.      *    const nodes have no information for us, so we return nil.
  983.      * ----------------
  984.      */
  985.     if (ExactNodeType(expr,Const))
  986.     return LispNil;
  987.     
  988.     /* ----------------
  989.      *    var nodes are what we want.. so we check if
  990.      *  the var node applies to the relation we want
  991.      *  and if it does, we return the var's attribute number
  992.      *  in a list.  If the var is not associated with
  993.      *  the relation we are interested in then we just return nil.
  994.      * ----------------
  995.      */
  996.     if (ExactNodeType(expr,Var)) {
  997.     Index varno;
  998.     AttributeNumber relno;
  999.     AttributeNumber attno;
  1000.     
  1001.     relno = CInteger(CAR(relationNum));
  1002.     varno = get_varno((Var)expr);
  1003.     attno = get_varattno((Var) expr);
  1004.     
  1005.     if (varno == relno)
  1006.         return lispCons(lispInteger(attno), LispNil);
  1007.     else
  1008.         return LispNil;
  1009.     }
  1010.     /* ----------------
  1011.      *    operator expressions may have var nodes in their
  1012.      *  opargs so we recursively search for var nodes there..
  1013.      * ----------------
  1014.      */
  1015.     if (is_clause(expr)) {
  1016.     List opargs;
  1017.     opargs = (List) get_opargs(expr);
  1018.     return ExecCollect(opargs,               /* list */
  1019.                ExecGetVarAttlistFromExpr, /* apply function */
  1020.                ExecUniqueCons,          /* collect function */
  1021.                relationNum);           /* apply parameters */
  1022.     } 
  1023.     /* ----------------
  1024.      *    function expressions are just like operator expressions..
  1025.      *  we scan the function expression's arg list to find the var nodes
  1026.      *  from which we get attribute numbers
  1027.      * ----------------
  1028.      */
  1029.     if (is_funcclause(expr)) {
  1030.     List funcargs;
  1031.     funcargs = (List) get_funcargs(expr);
  1032.     return ExecCollect(funcargs,               /* list */
  1033.                ExecGetVarAttlistFromExpr, /* apply function */
  1034.                ExecUniqueCons,          /* collect function */
  1035.                relationNum);           /* apply parameters */
  1036.     }
  1037.     /* ----------------
  1038.      *    for or clauses, we scan each of the or expressions
  1039.      *  because they may contain var nodes also..
  1040.      * ----------------
  1041.      */
  1042.     if (or_clause(expr)) {
  1043.     List clauseargs;
  1044.     clauseargs = (List) get_orclauseargs(expr);
  1045.     return ExecCollect(clauseargs,               /* list */
  1046.                ExecGetVarAttlistFromExpr, /* apply function */
  1047.                ExecUniqueCons,          /* collect function */
  1048.                relationNum);           /* apply parameters */
  1049.     }
  1050.     /* ----------------
  1051.      *    finally, not clauses are easy, we just return the
  1052.      *  attributes from the not clause's argument..
  1053.      * ----------------
  1054.      */
  1055.     if (not_clause(expr)) {
  1056.     List notclausearg;
  1057.     notclausearg = (List) get_notclausearg(expr);
  1058.     return
  1059.         ExecGetVarAttlistFromExpr((Node) notclausearg, relationNum);
  1060.     }
  1061.     
  1062.     /* ----------------
  1063.      *    if expr is not one of the above, our structure is likely
  1064.      *  corrupted but then we know there ain't no var nodes so
  1065.      *  we return nil and keep-a-processing...
  1066.      * ----------------
  1067.      */
  1068.     elog(DEBUG, "ExecGetVarAttlistFromExpr: invalid node type in expr!");
  1069.     return LispNil;
  1070. }
  1071.  
  1072. /* --------------------------------
  1073.  *    ExecGetVarAttlistFromTLE
  1074.  *
  1075.  *    This is simple.. Just extract the expression from
  1076.  *    the target list entry and have ExecGetAttlistFromExpr
  1077.  *    do our work for us..
  1078.  * --------------------------------
  1079.  */
  1080. /**** xxref:
  1081.  *           <apparently-unused>
  1082.  ****/
  1083. List
  1084. ExecGetVarAttlistFromTLE(tle, relationNum)
  1085.     List tle;
  1086.     List relationNum;    
  1087. {
  1088.     Node expr;
  1089.     
  1090.     expr =  (Node) tl_expr(tle);
  1091.     return
  1092.     ExecGetVarAttlistFromExpr(expr, relationNum);
  1093. }
  1094.  
  1095. /* --------------------------------
  1096.  *    ExecMakeAttsFromList
  1097.  *
  1098.  *    Returns an array of AttributeNumber's given a list,
  1099.  *      and returns the size of the array in it's second parameter.
  1100.  * --------------------------------
  1101.  */
  1102. /**** xxref:
  1103.  *           ExecInitScanAttributes
  1104.  ****/
  1105. AttributeNumberPtr
  1106. ExecMakeAttsFromList(attlist, numAttsPtr)
  1107.     List attlist;
  1108.     int     *numAttsPtr;
  1109. {
  1110.     List        cdrEntry;
  1111.     List        entry;
  1112.     int         len;
  1113.     AttributeNumberPtr  attnums;
  1114.     int            i;
  1115.     
  1116.     len = length(attlist);
  1117.     CXT1_printf("ExecMakeAttsFromList: context is %d\n", CurrentMemoryContext);
  1118.     attnums = (AttributeNumberPtr)
  1119.     palloc(len * sizeof(AttributeNumber));
  1120.     i = 0;
  1121.     foreach (cdrEntry, attlist) {
  1122.     entry = CAR(cdrEntry);
  1123.     attnums[i++] = CInteger(entry);
  1124.     }
  1125.     if (numAttsPtr != NULL)
  1126.     (*numAttsPtr) = i;
  1127.     
  1128.     return attnums;
  1129. }
  1130.  
  1131. /* --------------------------------
  1132.  *    ExecInitScanAttributes
  1133.  *
  1134.  *    This inspects the node's target list and initializes
  1135.  *    an array of attribute numbers stored in the node.
  1136.  *
  1137.  *    This array describe which attributes of the scanned
  1138.  *    tuple are ever examined or returned.  The rule manager
  1139.  *    uses this information to know which attributes are going
  1140.  *    to be inspected.
  1141.  *
  1142.  *    This is nontrivial because we have to walk the
  1143.  *    entire target list structure and find all the var
  1144.  *    nodes with varno's equal to the index (in the range table)
  1145.  *    of the relation being scanned by the node..
  1146.  *
  1147.  *    XXX:  If a user defined function/operator references
  1148.  *          attributes in some wierd indirect way, then the
  1149.  *          rule manager might not know to do the right thing
  1150.  *          because we don't detect this.
  1151.  *
  1152.  *          In these circumstance, we have to have the rule manager
  1153.  *          message every attribute of the tuple and we need to
  1154.  *          know somehow that the function can manipulate the tuple
  1155.  *          in some unexpected manner..
  1156.  *
  1157.  *    Note: the memory used by the cons cells in our
  1158.  *    temporary lists is not reclaimed until the end of transaction.
  1159.  *    (A better setup would free the memory as we go.)
  1160.  *
  1161.  *    Here is one instance where it would be much easier
  1162.  *    to write this in lisp..
  1163.  * --------------------------------
  1164.  */
  1165. /**** xxref:
  1166.  *           ExecInitIndexScan
  1167.  *           ExecInitSeqScan
  1168.  ****/
  1169. void
  1170. ExecInitScanAttributes(node)
  1171.     Plan node;
  1172. {
  1173.     ScanState        scanstate;
  1174.     List        targetList;
  1175.     AttributeNumberPtr     scanAtts;
  1176.     int            numScanAtts;
  1177.     List        attlist;
  1178.     
  1179.     /* ----------------
  1180.      *    make sure we have a scan node
  1181.      * ----------------
  1182.      */
  1183.     if (!ExecIsSeqScan(node) && !ExecIsIndexScan(node)) {
  1184.     elog(DEBUG, "ExecInitScanAttributes: called on non scan node");
  1185.     return;
  1186.     }
  1187.     
  1188.     /* ----------------
  1189.      *    XXX currently we assign attlist = LispNil which forces
  1190.      *      ExecScan() to generate the attribute information
  1191.      *      at runtime when the first tuple is retrieved.
  1192.      *
  1193.      *        This is a poor long-term solution because that
  1194.      *        means the rule-manager ends up inspecting every
  1195.      *        attribute of every tuple scanned..  But this will
  1196.      *        work for now.. -cim 10/12/89
  1197.      * ----------------
  1198.      */
  1199.     attlist = LispNil;
  1200.  
  1201.     /* ----------------
  1202.      *  get information from the node.. 
  1203.      *    Note: both indexscans and seqscans have scanstates since
  1204.      *  indexscans inherit from seqscans.
  1205.      * ----------------
  1206.      */
  1207.     scanstate =  get_scanstate((Scan) node);
  1208.     
  1209. #ifdef PERHAPSNEVER
  1210.     /* ----------------
  1211.      *    need the range table index of the scanned relation
  1212.      *  into relno so we know which var nodes to inspect.
  1213.      *  ExecCollect expects a list so we put it in one..
  1214.      * ----------------
  1215.      */
  1216.     targetList =  get_qptargetlist(node);
  1217.     
  1218.     relno =       get_scanrelid(node);
  1219.     relationNum = lispCons(lispInteger(relno), LispNil);
  1220.     
  1221.     /* ----------------
  1222.      *    construct a list of all the attributes using ExecCollect
  1223.      * ----------------
  1224.      */
  1225.     attlist = ExecCollect(targetList,             /* list */
  1226.               ExecGetVarAttlistFromTLE, /* apply function */
  1227.               ExecUniqueCons,        /* collect function */
  1228.               relationNum);         /* apply parameters */
  1229.     
  1230.     if (ExecIsIndexScan(node)) {
  1231.     /* ----------------
  1232.      *  we might also inspect the indxqual clauses in the
  1233.      *  index node for additional attribute number information
  1234.      *  but I don't understand how to do this now.. -cim 9/21/89
  1235.      * ----------------
  1236.      */
  1237.     }
  1238.  
  1239.     /* XXX should also inspect qpqual */
  1240. #endif PERHAPSNEVER
  1241.     
  1242.     /* ----------------
  1243.      *    make attribute array from attlist.
  1244.      * ----------------
  1245.      */
  1246.     if (lispNullp(attlist)) {
  1247.     scanAtts = NULL;
  1248.     numScanAtts = 0;
  1249.     } else
  1250.     scanAtts = ExecMakeAttsFromList(attlist, &numScanAtts);
  1251.     
  1252.     /* ----------------
  1253.      *    set the node's attribute information
  1254.      * ----------------
  1255.      */
  1256.     set_cs_ScanAttributes((CommonState) scanstate, scanAtts);
  1257.     set_cs_NumScanAttributes((CommonState) scanstate, numScanAtts);
  1258. }
  1259.  
  1260. /* --------------------------------
  1261.  *    ExecMakeBogusScanAttributes
  1262.  *
  1263.  *    This makes an array of size natts containing the
  1264.  *    attribute numbers from 1 to natts.
  1265.  * --------------------------------
  1266.  */
  1267. AttributeNumberPtr
  1268. ExecMakeBogusScanAttributes(natts)
  1269.     int natts;
  1270. {
  1271.     extern MemoryContext PortalExecutorHeapMemory;
  1272.     AttributeNumberPtr   scanAtts;
  1273.     int             scanAttSize;
  1274.     int             i;
  1275.  
  1276.     /* ----------------
  1277.      *    calculate size of our array
  1278.      * ----------------
  1279.      */
  1280.     scanAttSize = natts * sizeof(AttributeNumber);
  1281.         
  1282.     /* ----------------
  1283.      *  if we are running in a portal, we have to make
  1284.      *  sure our allocations occur in the proper context
  1285.      *  lest they go away unexpectedly.  This is a hack
  1286.      *  to preserve this memory for the lifetime of the
  1287.      *  portal (I think).  -cim 3/15/90
  1288.      * ----------------
  1289.      */
  1290.     if (PortalExecutorHeapMemory != NULL)
  1291.     scanAtts = (AttributeNumberPtr)
  1292.         MemoryContextAlloc(PortalExecutorHeapMemory, scanAttSize);
  1293.     else
  1294.     scanAtts = (AttributeNumberPtr)
  1295.         palloc(scanAttSize);
  1296.     
  1297.     /* ----------------
  1298.      *    fill the scan attributes array
  1299.      * ----------------
  1300.      */
  1301.     for (i=1; i<=natts; i++) {
  1302.     scanAtts[i-1] = i;
  1303.     }    
  1304.  
  1305.     return scanAtts;
  1306. }
  1307.     
  1308.  
  1309. /* --------------------------------
  1310.  *    ExecFreeScanAttributes
  1311.  *
  1312.  *    This frees the allocated array of attribute numbers.
  1313.  *
  1314.  *    Note: it is not an error to pass NULL.  That just means
  1315.  *    that no attribute information was allocated.
  1316.  * --------------------------------
  1317.  */
  1318.  
  1319. /**** xxref:
  1320.  *           ExecEndIndexScan
  1321.  *           ExecEndSeqScan
  1322.  ****/
  1323. void
  1324. ExecFreeScanAttributes(ptr)
  1325.     AttributeNumberPtr ptr;
  1326. {
  1327.     extern MemoryContext PortalExecutorHeapMemory;
  1328.  
  1329.     /* ----------------
  1330.      *    don't free an invalid pointer
  1331.      * ----------------
  1332.      */
  1333.     if (ptr == NULL)
  1334.     return;
  1335.  
  1336.     /* ----------------
  1337.      *    make certain we free the attribute list in the proper
  1338.      *  memory context.  Again, this is a crappy hack which comes
  1339.      *  from retrofitting portals into the executor.
  1340.      * ----------------
  1341.      */
  1342.     if (PortalExecutorHeapMemory != NULL)
  1343.     MemoryContextFree(PortalExecutorHeapMemory, (Pointer) ptr);
  1344.     else
  1345.     pfree(ptr);
  1346. }
  1347.  
  1348. /* function that returns number of atts in a var */
  1349. int
  1350. ExecGetVarLen(node, commonstate, var)
  1351. Plan node;
  1352. CommonState commonstate;
  1353. Var var;
  1354. {
  1355.     int varno, varattno;
  1356.     TupleTableSlot    slot;
  1357.     ExecTupDescriptor   execTupDesc;
  1358.     int len;
  1359.     Plan varplan;
  1360.  
  1361.     if (node == NULL) return 0;
  1362.     varno = get_varno(var);
  1363.     varattno = get_varattno(var);
  1364.     if (varno == INNER)
  1365.     varplan = get_innerPlan(node);
  1366.     else
  1367.     varplan = get_outerPlan(node);
  1368.     if (varattno == 0) {
  1369.     if (varplan == NULL) {
  1370.         /* this must be a scan */
  1371.         Relation curRel;
  1372.         curRel = get_css_currentRelation((CommonScanState)commonstate);
  1373.         len = curRel->rd_rel->relnatts;
  1374.       }
  1375.     else
  1376.         len = ExecTargetListLength(get_qptargetlist(varplan));
  1377.       }
  1378.     else {
  1379.         slot = NodeGetResultTupleSlot(varplan);
  1380.         execTupDesc = ExecSlotExecDescriptor(slot);
  1381.         len = execTupDesc->data[varattno-1]->len;
  1382.       }
  1383.     return len;
  1384. }
  1385.  
  1386. /* function that returns the Tuple Descriptor for a var */
  1387. TupleDescriptor
  1388. ExecGetVarTupDesc(node, commonstate, var)
  1389. Plan node;
  1390. CommonState commonstate;
  1391. Var var;
  1392. {
  1393.     int varno, varattno;
  1394.     TupleTableSlot    slot;
  1395.     ExecTupDescriptor   execTupDesc;
  1396.     TupleDescriptor tupdesc;
  1397.     Plan varplan;
  1398.  
  1399.     if (node == NULL) return 0;
  1400.     varno = get_varno(var);
  1401.     varattno = get_varattno(var);
  1402.     if (varno == INNER)
  1403.     varplan = get_innerPlan(node);
  1404.     else
  1405.     varplan = get_outerPlan(node);
  1406.     if (varattno == 0) {
  1407.     if (varplan == NULL) {
  1408.         /* this must be a scan */
  1409.         Relation curRel;
  1410.         curRel = get_css_currentRelation((CommonScanState)commonstate);
  1411.         tupdesc = &curRel->rd_att;
  1412.       }
  1413.     else
  1414.         tupdesc = ExecGetTupType(varplan);
  1415.       }
  1416.     else {
  1417.         execTupDesc = ExecGetExecTupDesc(varplan);
  1418.         tupdesc = execTupDesc->data[varattno-1]->attdesc;
  1419.       }
  1420.     return tupdesc;
  1421. }
  1422.